package com.hisense.ovcloud.warehouse.routers;

import com.hisense.ovcloud.commons.configs.base.BaseResponse;
import com.hisense.ovcloud.commons.configs.validator.BaseRouterConfiguration;
import com.hisense.ovcloud.warehouse.dto.req.*;
import com.hisense.ovcloud.warehouse.service.PlatformService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import org.springdoc.core.annotations.RouterOperation;
import org.springdoc.core.annotations.RouterOperations;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.validation.Validator;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.reactive.function.server.RouterFunction;
import org.springframework.web.reactive.function.server.RouterFunctions;
import org.springframework.web.reactive.function.server.ServerResponse;
import reactor.core.publisher.SynchronousSink;

import javax.annotation.PostConstruct;
import java.util.function.BiConsumer;

import static org.springframework.web.reactive.function.server.RequestPredicates.path;
import static org.springframework.web.reactive.function.server.RouterFunctions.route;

@Configuration
public class PlatformConfiguration extends BaseRouterConfiguration {

    private final PlatformService platformService;

    private final Validator getKeyPairsReqValidator;

    private final Validator modifyKeyDescriptionReqValidator;

    private final Validator enableKeyPairReqValidator;

    private final Validator createProjectReqValidator;

    private final Validator getDeveloperByMajorDomainIdReqValidator;

    private final Validator deleteKeyPairReqValidator;

    private BiConsumer<GetKeyPairsReq, SynchronousSink<GetKeyPairsReq>> getKeyPairsReqValidatorHandler;
    private BiConsumer<ModifyKeyDescriptionReq, SynchronousSink<ModifyKeyDescriptionReq>> modifyKeyDescriptionReqValidatorHandler;
    private BiConsumer<EnableKeyPairReq, SynchronousSink<EnableKeyPairReq>> enableKeyPairReqValidatorHandler;
    private BiConsumer<CreateProjectReq, SynchronousSink<CreateProjectReq>> createProjectReqValidatorHandler;
    private BiConsumer<GetDeveloperByMajorDomainIdReq, SynchronousSink<GetDeveloperByMajorDomainIdReq>> getDeveloperByMajorDomainIdReqValidatorHandler;
    private BiConsumer<DeleteKeyPairReq, SynchronousSink<DeleteKeyPairReq>> deleteKeyPairReqValidatorValidatorHandler;

    @PostConstruct
    public void init() {
        getKeyPairsReqValidatorHandler = (body, sink) -> validate(sink, getKeyPairsReqValidator, body, GetKeyPairsReq.class);
        modifyKeyDescriptionReqValidatorHandler = (body, sink) -> validate(sink, modifyKeyDescriptionReqValidator, body, ModifyKeyDescriptionReq.class);
        enableKeyPairReqValidatorHandler = (body, sink) -> validate(sink, enableKeyPairReqValidator, body, EnableKeyPairReq.class);
        createProjectReqValidatorHandler = (body, sink) -> validate(sink, createProjectReqValidator, body, CreateProjectReq.class);
        getDeveloperByMajorDomainIdReqValidatorHandler = (body, sink) -> validate(sink, getDeveloperByMajorDomainIdReqValidator, body, GetDeveloperByMajorDomainIdReq.class);
        deleteKeyPairReqValidatorValidatorHandler = (body, sink) -> validate(sink, deleteKeyPairReqValidator, body, DeleteKeyPairReq.class);
    }

    public PlatformConfiguration(PlatformService platformService, @Qualifier("getKeyPairsReqValidator") Validator getKeyPairsReqValidator, @Qualifier("modifyKeyDescriptionReqValidator") Validator modifyKeyDescriptionReqValidator, @Qualifier("enableKeyPairReqValidator") Validator enableKeyPairReqValidator, @Qualifier("createProjectReqValidator") Validator createProjectReqValidator, @Qualifier("getDeveloperByMajorDomainIdReqValidator") Validator getDeveloperByMajorDomainIdReqValidator, @Qualifier("deleteKeyPairReqValidator") Validator deleteKeyPairReqValidator) {
        this.platformService = platformService;
        this.getKeyPairsReqValidator = getKeyPairsReqValidator;
        this.modifyKeyDescriptionReqValidator = modifyKeyDescriptionReqValidator;
        this.enableKeyPairReqValidator = enableKeyPairReqValidator;
        this.createProjectReqValidator = createProjectReqValidator;
        this.getDeveloperByMajorDomainIdReqValidator = getDeveloperByMajorDomainIdReqValidator;
        this.deleteKeyPairReqValidator = deleteKeyPairReqValidator;
    }

    @Bean
    @RouterOperations({
            @RouterOperation(
                    path = "/ac-platform/getKeyPairs",
                    method = RequestMethod.POST,
                    produces = "application/json",
                    operation = @Operation(
                            operationId = "getKeyPairs",
                            description = "getKeyPairs",
                            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                                    description = "GetKeyPairsReq",
                                    required = true,
                                    content = {
                                            @Content(
                                                    mediaType = "application/json",
                                                    schema = @Schema(implementation = GetKeyPairsReq.class)
                                            )
                                    }
                            ),
                            responses = {
                                    @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = BaseResponse.class)))
                            }
                    )
            ),
            @RouterOperation(
                    path = "/ac-platform/createKeyPair",
                    method = RequestMethod.POST,
                    produces = "application/json",
                    operation = @Operation(
                            operationId = "createKeyPair",
                            description = "createKeyPair",
                            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                                    description = "GetKeyPairsReq",
                                    required = true,
                                    content = {
                                            @Content(
                                                    mediaType = "application/json",
                                                    schema = @Schema(implementation = GetKeyPairsReq.class)
                                            )
                                    }
                            ),
                            responses = {
                                    @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = BaseResponse.class)))
                            }
                    )
            ),
            @RouterOperation(
                    path = "/ac-platform/modifyKeyDescription",
                    method = RequestMethod.POST,
                    produces = "application/json",
                    operation = @Operation(
                            operationId = "modifyKeyDescription",
                            description = "modifyKeyDescription",
                            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                                    description = "ModifyKeyDescriptionReq",
                                    required = true,
                                    content = {
                                            @Content(
                                                    mediaType = "application/json",
                                                    schema = @Schema(implementation = ModifyKeyDescriptionReq.class)
                                            )
                                    }
                            ),
                            responses = {
                                    @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = BaseResponse.class)))
                            }
                    )
            ),
            @RouterOperation(
                    path = "/ac-platform/enableKeyPair",
                    method = RequestMethod.POST,
                    produces = "application/json",
                    operation = @Operation(
                            operationId = "enableKeyPair",
                            description = "enableKeyPair",
                            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                                    description = "EnableKeyPairReq",
                                    required = true,
                                    content = {
                                            @Content(
                                                    mediaType = "application/json",
                                                    schema = @Schema(implementation = EnableKeyPairReq.class)
                                            )
                                    }
                            ),
                            responses = {
                                    @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = BaseResponse.class)))
                            }
                    )
            ),
            @RouterOperation(
                    path = "/ac-platform/deleteKeyPair",
                    method = RequestMethod.POST,
                    produces = "application/json",
                    operation = @Operation(
                            operationId = "deleteKeyPair",
                            description = "deleteKeyPair",
                            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                                    description = "ModifyKeyDescriptionReq",
                                    required = true,
                                    content = {
                                            @Content(
                                                    mediaType = "application/json",
                                                    schema = @Schema(implementation = ModifyKeyDescriptionReq.class)
                                            )
                                    }
                            ),
                            responses = {
                                    @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = BaseResponse.class)))
                            }
                    )
            ),
            @RouterOperation(
                    path = "/ac-platform/createProject",
                    method = RequestMethod.POST,
                    produces = "application/json",
                    operation = @Operation(
                            operationId = "createProject",
                            description = "createProject",
                            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                                    description = "CreateProjectReq",
                                    required = true,
                                    content = {
                                            @Content(
                                                    mediaType = "application/json",
                                                    schema = @Schema(implementation = CreateProjectReq.class)
                                            )
                                    }
                            ),
                            responses = {
                                    @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = BaseResponse.class)))
                            }
                    )
            ),
            @RouterOperation(
                    path = "/ac-platform/getDeveloperByMajorDomainId",
                    method = RequestMethod.POST,
                    produces = "application/json",
                    operation = @Operation(
                            operationId = "getDeveloperByMajorDomainId",
                            description = "getDeveloperByMajorDomainId",
                            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                                    description = "GetDeveloperByMajorDomainIdReq",
                                    required = true,
                                    content = {
                                            @Content(
                                                    mediaType = "application/json",
                                                    schema = @Schema(implementation = GetDeveloperByMajorDomainIdReq.class)
                                            )
                                    }
                            ),
                            responses = {
                                    @ApiResponse(responseCode = "200", description = "OK", content = @Content(schema = @Schema(implementation = BaseResponse.class)))
                            }
                    )
            )
    })
    public RouterFunction<ServerResponse> platformRoutes() {
        return RouterFunctions.nest(path("/ac-platform"),
                route()
                        .POST("/getKeyPairs", req -> ServerResponse.ok().body(platformService.getKeyPairs(req.bodyToMono(GetKeyPairsReq.class).handle(getKeyPairsReqValidatorHandler)),
                                BaseResponse.class))
                        .POST("/createKeyPair", req -> ServerResponse.ok().body(platformService.createKeyPair(req.bodyToMono(GetKeyPairsReq.class).handle(getKeyPairsReqValidatorHandler)),
                                BaseResponse.class))
                        .POST("/modifyKeyDescription", req -> ServerResponse.ok().body(platformService.modifyKeyDescription(req.bodyToMono(ModifyKeyDescriptionReq.class).handle(modifyKeyDescriptionReqValidatorHandler)),
                                BaseResponse.class))
                        .POST("/enableKeyPair", req -> ServerResponse.ok().body(platformService.enableKeyPair(req.bodyToMono(EnableKeyPairReq.class).handle(enableKeyPairReqValidatorHandler)),
                                BaseResponse.class))
                        .POST("/deleteKeyPair", req -> ServerResponse.ok().body(platformService.deleteKeyPair(req.bodyToMono(DeleteKeyPairReq.class).handle(deleteKeyPairReqValidatorValidatorHandler)),
                                BaseResponse.class))
                        .POST("/createProject", req -> ServerResponse.ok().body(platformService.createProject(req.bodyToMono(CreateProjectReq.class).handle(createProjectReqValidatorHandler)),
                                BaseResponse.class))
                        .POST("/getDeveloperByMajorDomainId", req -> ServerResponse.ok().body(platformService.getDeveloperByMajorDomainId(req.bodyToMono(GetDeveloperByMajorDomainIdReq.class).handle(getDeveloperByMajorDomainIdReqValidatorHandler)),
                                BaseResponse.class))
                        .build());
    }
}

